/**
 * @file       semaphore.hpp
 * @author     WMQ
 * @date       2024/12/21
 * @brief      信号量
 */
#ifndef SEMAPHORE_HPP
#define SEMAPHORE_HPP

#include <condition_variable>
#include <cstdint>
#include <mutex>

class Semaphore
{
public:
    /**
     * @brief 构造函数
     * @param[in] count 信号量的起始值
     */
    explicit Semaphore(int32_t count) : count_(count) {}

    /**
     * @brief 等待信号值直至大于0并减1
     */
    void Wait()
    {
        std::unique_lock<std::mutex> lock(mtx_);
        cond_.wait(lock, [this]() {
            return count_ > 0;
        });
        --count_;
    }

    /**
     * @brief 在一定时间内等待信号值直至大于0并减1
     * @param[in] wait_time 等待的时间(ms)
     * @return
     *  true   成功 \n
     *  false  失败 \n
     * @note
     *   回拨系统时间可能会导致无法超时
     */
    bool WaitFor(int32_t wait_time)
    {
        std::unique_lock<std::mutex> lock(mtx_);
        if (cond_.wait_for(lock, std::chrono::milliseconds(wait_time), [this]() {
                return count_ > 0;
            }))
        {
            --count_;
            return true;
        }

        return false;
    }

    /**
     * @brief 信号值加1并唤醒一个等待
     */
    void Signal()
    {
        {
            std::lock_guard<std::mutex> lock(mtx_);
            ++count_;
        }
        cond_.notify_one();
    }

private:
    std::mutex mtx_;
    std::condition_variable cond_;
    int32_t count_;
};

#endif